package org.budo.dubbo.protocol.http.authentication;

import java.io.IOException;
import java.io.Serializable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.budo.support.mvcs.Mvcs;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * Mvc 过滤器
 * 
 * @author limingwei
 */
@Slf4j
@Getter
@Setter
public class AuthenticationCheckHandlerInterceptor extends AbstractAuthenticationCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (null == handler || !(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Boolean require = AuthenticationCheckUtil.requireAuthenticationCheck_mvc(handlerMethod);
        if (null == require) {
            require = this.getDefaultAuthenticationCheck();
        }

        if (!require) {
            return true;
        }

        AuthenticationCheckService authenticationCheckService = this.getAuthenticationCheckService();
        Serializable authenticationPrincipal = authenticationCheckService.getAuthenticationPrincipal();
        Boolean check = this.checkAuthenticationPrincipal(authenticationPrincipal, request, handler);
        if (!check) {
            log.warn("#44 authenticationPrincipal=" + authenticationPrincipal + ", authenticationCheckService=" + authenticationCheckService);

            this.handleAuthFailed(request, response, handler);
            return false;
        }

        return true;
    }

    protected Boolean checkAuthenticationPrincipal(Serializable authenticationPrincipal, HttpServletRequest request, Object handler) {
        return null != authenticationPrincipal && !(authenticationPrincipal instanceof AuthenticationCheckService.Fail);
    }

    /**
     * 用户未登陆时的处理逻辑
     */
    protected void handleAuthFailed(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String loginUrl = this.getLoginUrl();

        if (null != loginUrl && !loginUrl.isEmpty()) {
            response.sendRedirect(loginUrl);
            return;
        }

        response.setHeader("AuthenticationCheckHandlerInterceptorHandleAuthFailed", "AuthenticationCheckHandlerInterceptorHandleAuthFailed");

        log.error("#70 loginUrl 没有配置, this=" + this + ", request=" + request + ", handler=" + handler + ", headers=" + Mvcs.getRequestHeaderMap(request));
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //
    }
}